import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { UniformEditorDataUtil } from '@farris/designer-services';
import { CodeEditorComponent } from '@farris/designer-devkit';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { InputProps } from '../../common/property/input-property-config';

export class NumberRangeProp extends InputProps {

  propertyConfig: ElementPropertyConfig[];

  getPropConfig(propertyData: any): ElementPropertyConfig[] {
    this.propertyConfig = [];

    // 基本信息属性
    const basicPropConfig = this.getBasicPropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(basicPropConfig);

    // 外观属性
    const appearanceProperties = this.getAppearancePropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(appearanceProperties);

    // 行为属性
    const behaviorPropConfig = this.getBehaviorPropConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(behaviorPropConfig);

    // 扩展区域属性
    // const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, this.viewModelId);
    // this.propertyConfig.push(appendPropConfig);

    // 表达式属性
    const exprPropConfig = this.getExpressionPropConfig(propertyData, this.viewModelId);
    if (exprPropConfig) {
      this.propertyConfig.push(exprPropConfig);
    }

    // 事件属性
    const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId);
    this.propertyConfig.push(eventPropConfig);

    return this.propertyConfig;
  }


  /**
   * 外观属性
   */
  private getAppearancePropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
    const self = this;
    let appearanceProperties = [];
    if (showPosition === 'card' || showPosition === 'tableTdEditor') {
      appearanceProperties = this.getAppearanceCommonPropConfig(propertyData, viewModelId, showPosition);
    }

    appearanceProperties.push(
      {
        propertyID: 'textAlign',
        propertyName: '数据水平对齐方式',
        propertyType: 'select',
        description: '数据水平对齐方式设置',
        defaultValue: 'left',
        iterator: [{ key: 'left', value: '靠左' }, { key: 'right', value: '靠右' }, { key: 'center', value: '居中' }]
      },
    );
    const config = {
      categoryId: 'appearance',
      categoryName: '外观',
      properties: appearanceProperties,
      setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

        if (!changeObject) {
          return;
        }
        self.changeAppearancePropertyRelates(this.properties, changeObject, propertyData, parameters);
      }

    };
    if (showPosition !== 'card') {
      Object.assign(config, {
        categoryId: showPosition + '_' + config.categoryId,
        propertyData,
        enableCascade: true,
        parentPropertyID: 'editor',
        tabId: showPosition,
        tabName: '编辑器'
      });
    }
    return config;
  }

  /**
   * 行为属性
   */
  private getBehaviorPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

    // 获取绑定字段schema中的长度、精度属性
    let maxLength;
    let maxPrecision;
    if (propertyData.binding && propertyData.binding.type === 'Form') {
      const fieldInfo = this.schemaService.getFieldByIDAndVMID(propertyData.binding.field, viewModelId);
      if (fieldInfo && fieldInfo.schemaField) {
        maxLength = fieldInfo.schemaField.type.length;
        maxPrecision = fieldInfo.schemaField.type.precision;
      }
    }
    let behaviorProperties = [];
    if (showPosition === 'card' || showPosition === 'tableTdEditor') {
      behaviorProperties = this.getBehaviorCommonPropConfig(propertyData, viewModelId);
    }

    behaviorProperties.push(

      {
        propertyID: 'maxLength',
        propertyName: '取值最大长度',
        propertyType: 'number',
        description: '取值最大长度设置',
        decimals: 0,
        min: 0,
        max: maxLength
      },
      {
        propertyID: 'maxValue',
        propertyName: '最大值',
        propertyType: 'number',
        description: '数字最大值设置',
        min: propertyData.minValue ? propertyData.minValue : undefined,
        decimals: propertyData.precision,
        isBigNumber: propertyData.bigNumber
      },
      {
        propertyID: 'minValue',
        propertyName: '最小值',
        propertyType: 'number',
        description: '数字最小值设置',
        max: propertyData.maxValue ? propertyData.maxValue : undefined,
        decimals: propertyData.precision,
        isBigNumber: propertyData.bigNumber
      },
      {
        propertyID: 'precisionSourceType',
        propertyName: '精度类型',
        propertyType: 'select',
        description: '数字精度类型设置',
        iterator: [{ key: 'static', value: '静态' }, { key: 'dynamic', value: '动态' }],
        visible: maxPrecision !== 0
      },
      {
        propertyID: 'precision',
        propertyName: '精度',
        propertyType: 'number',
        description: '数字精度设置',
        decimals: 0,
        min: 0,
        max: maxPrecision,
        visible: propertyData.precisionSourceType === 'static',
      },
      {
        propertyID: 'precisionDataSource',
        propertyName: '精度数据源',
        propertyType: 'unity',
        description: '数字精度数据源设置',
        editorParams: {
          controlName: UniformEditorDataUtil.getControlName(propertyData),
          editorOptions: {
            types: ['variable'],
            variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
            getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService)
          }
        },
        visible: propertyData.precisionSourceType === 'dynamic'
      },
      {
        propertyID: 'useThousands',
        propertyName: '使用千分值',
        propertyType: 'boolean',
        description: '是否使用千分值',
        defaultValue: true
      },
      {
        propertyID: 'formatter',
        propertyName: '格式化',
        propertyType: 'modal',
        description: '格式化设置',
        editor: CodeEditorComponent,
        editorParams: {
          language: 'javascript',
          exampleCode:
            "\r\n (value: number): string | number => {\r\n    return '$' + value;\r\n}\r\n"
        }
      },
      {
        propertyID: 'parser',
        propertyName: '反格式化',
        propertyType: 'modal',
        description: '反格式化设置',
        editor: CodeEditorComponent,
        editorParams: {
          language: 'javascript',
          exampleCode:
            "\r\n (value: string):number => {\r\n    return  Number(value.substring(1));\r\n}\r\n"
        }
      }
    );

    const self = this;
    const config = {
      categoryId: 'behavior',
      categoryName: '行为',
      properties: behaviorProperties,
      setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters) {
        if (!changeObject) {
          return;
        }
        self.changeBehaviorPropertyRelates(this.properties, changeObject, propertyData, parameters, showPosition);

        switch (changeObject && changeObject.propertyID) {
          case 'maxValue': {
            const minProp = this.properties.find(p => p.propertyID === 'minValue');
            if (minProp) {
              minProp.max = changeObject.propertyValue ? changeObject.propertyValue : undefined;
            }
            break;
          }
          case 'minValue': {
            const maxProp = this.properties.find(p => p.propertyID === 'maxValue');
            if (maxProp) {
              maxProp.min = changeObject.propertyValue ? changeObject.propertyValue : undefined;
            }
            break;
          }
          case 'precision': {
            const maxProp = this.properties.find(p => p.propertyID === 'maxValue');
            if (maxProp) {
              maxProp.decimals = changeObject.propertyValue;
            }
            const minProp = this.properties.find(p => p.propertyID === 'minValue');
            if (minProp) {
              minProp.decimals = changeObject.propertyValue;
            }
            break;
          }
          case 'precisionSourceType': {
            const precision = this.properties.find(p => p.propertyID === 'precision');
            if (precision) {
              precision.visible = changeObject.propertyValue === 'static';
            }
            const precisionDataSource = this.properties.find(p => p.propertyID === 'precisionDataSource');
            if (precisionDataSource) {
              precisionDataSource.visible = changeObject.propertyValue === 'dynamic';
            }
            break;
          }
        }
      }

    };

    if (showPosition !== 'card') {
      Object.assign(config, {
        categoryId: showPosition + '_' + config.categoryId,
        propertyData,
        enableCascade: true,
        parentPropertyID: 'editor',
        tabId: showPosition,
        tabName: '编辑器'
      });
    }
    return config;
  }

  /**
   * 列编辑器属性
   * @param gridFieldData 列数据
   */
  getGridFieldEdtiorPropConfig(gridFieldData: any, viewModelId: string) {
    const propertyData = gridFieldData.editor;

    this.propertyConfig = [];

    // 编辑器类型属性
    const editorTypeConfig = this.getGridFieldEditorTypePropertyConfig(gridFieldData, viewModelId);
    if (editorTypeConfig) {
      this.propertyConfig.push(editorTypeConfig);
    }

    // 外观属性
    const apperanceConfig = this.getAppearancePropConfig(propertyData, viewModelId, 'gridFieldEditor');
    this.propertyConfig.push(apperanceConfig);

    // 行为属性
    const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'gridFieldEditor');
    this.appendBehaviorPropsForGridFieldEditor(behaviorConfig, propertyData, viewModelId);
    this.propertyConfig.push(behaviorConfig);

    // 事件属性
    const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId, 'gridFieldEditor');
    this.propertyConfig.push(eventPropConfig);

    return this.propertyConfig;
  }

  /**
   * table单元格编辑器属性
   * @param tdData 单元格数据
   * @param viewModelId viewModelId
   * @returns 属性配置
   */
  getTableTdEdtiorPropConfig(tdData: any, viewModelId: string): ElementPropertyConfig[] {
    const propertyData = tdData.editor;

    this.propertyConfig = [];

    // 外观属性
    const appearanceConfig = this.getAppearancePropConfig(propertyData, viewModelId, 'tableTdEditor');
    this.propertyConfig.push(appearanceConfig);


    // 行为属性
    const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'tableTdEditor');
    behaviorConfig.properties = behaviorConfig.properties.filter(p => !'binding,visible'.includes(p.propertyID));
    this.propertyConfig.push(behaviorConfig);

    // 扩展区域属性
    const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, viewModelId, 'tableTdEditor');
    this.propertyConfig.push(appendPropConfig);

    // 表达式属性
    const exprPropConfig = this.getExpressionPropConfig(propertyData, viewModelId, 'tableTdEditor');
    if (exprPropConfig) {
      this.propertyConfig.push(exprPropConfig);
    }

    // 事件属性
    const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId, 'tableTdEditor');
    this.propertyConfig.push(eventPropConfig);


    return this.propertyConfig;
  }

}
